package com.zhuanzhuan.hero.user.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhuanzhuan.hero.user.consts.NumConsts;
import com.zhuanzhuan.hero.user.dto.RelateUserGroupLabelDTO;
import com.zhuanzhuan.hero.user.entity.HeroLabelInfo;
import com.zhuanzhuan.hero.user.entity.HeroUserGroupLabelRelation;
import com.zhuanzhuan.hero.user.entity.HeroUserPrivacySetup;
import com.zhuanzhuan.hero.user.enums.*;
import com.zhuanzhuan.hero.user.exception.BusinessException;
import com.zhuanzhuan.hero.user.pojo.bo.LabelInfoQueryBO;
import com.zhuanzhuan.hero.user.service.*;
import com.zhuanzhuan.hero.user.vo.label.UserGroupLabelPageVO;
import com.zhuanzhuan.hero.user.vo.label.UserGroupLabelVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ClassName UserGroupServiceImpl
 * @Description
 * @Author hanjunjun
 * @Date 2024/6/26 10:59
 */
@Service
@Slf4j
public class UserGroupServiceImpl implements IUserGroupService {

    @Resource
    private HeroLabelInfoService labelInfoService;

    @Resource
    private HeroUserGroupLabelRelationService userGroupLabelRelationService;

    @Resource
    private HeroUserNotesService userNotesService;

    @Resource
    private HeroUserInfoService userInfoService;

    @Resource
    private HeroUserPrivacySetupService userPrivacySetupRecordService;

    @Override
    public UserGroupLabelVO addUserGroupLabel(Long uid, String groupName) {
        //最多20个  是否重名
        List<HeroLabelInfo> groupLabels = labelInfoService.listByParam(LabelInfoQueryBO.builder()
            .labelType(LabelTypeEnum.GROUP.getCode()).createUid(uid).build());
        if (groupLabels.size() >= NumConsts.TWENTY) {
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), "最多创建20个分组");
        }
        boolean exist = groupLabels.stream().anyMatch(label -> groupName.equals(label.getLabelName()));
        if (exist) {
            throw new BusinessException(ExceptionMsgEnum.BUSINESS_ERROR.getCode(), groupName + "分组已存在");
        }

        //保存
        HeroLabelInfo insertLabel = this.buildGroupLabel(groupName, uid);
        labelInfoService.save(insertLabel);

        UserGroupLabelVO resultVO = new UserGroupLabelVO();
        resultVO.setLabelId(insertLabel.getId()).setLabelName(groupName).setIsRelated(false);
        return resultVO;
    }

    @Override
    public UserGroupLabelPageVO queryGroupRelation(Long fromUid, Long toUid) {
        UserGroupLabelPageVO vo = new UserGroupLabelPageVO();

        vo.setNickname(Objects.requireNonNull(userInfoService.getUserByUid(toUid), ExceptionMsgEnum.DATA_NOT_EXIST.getErrorMsg())
            .getNickname());

        String notes = userNotesService.queryNotesByUid(fromUid, toUid);
        if (Objects.nonNull(notes)) {
            vo.setNotes(notes);
        }

        vo.setGroupLabels(this.queryUserGroup(fromUid, toUid));

        List<HeroUserPrivacySetup> userPrivacySetupRecords =
            userPrivacySetupRecordService.listByUid(fromUid, toUid);
        vo.setIsInvisible(userPrivacySetupRecords.stream()
            .anyMatch(privact -> PrivacyTypeEnum.INVISIBLE.getCode().equals(privact.getPrivacyType())) ?
            NumConsts.ONE : NumConsts.ZERO);
        vo.setIsBlock(userPrivacySetupRecords.stream()
            .anyMatch(privact -> PrivacyTypeEnum.BLOCK.getCode().equals(privact.getPrivacyType())) ?
            NumConsts.ONE : NumConsts.ZERO);

        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void relateUserGroupLabels(Long fromUid, RelateUserGroupLabelDTO relateUserGroupLabelDTO) {
        Long toUid = relateUserGroupLabelDTO.getToUid();

        if (fromUid.equals(toUid)) {
            log.info("uid相同");
            throw new BusinessException(ExceptionMsgEnum.PARAM_ERROR);
        }

        //设置备注
        userNotesService.setUpNotes(fromUid, toUid, relateUserGroupLabelDTO.getNotes());

        //关联分组标签
        List<Long> relatedGrouplabelIds = relateUserGroupLabelDTO.getRelatedGrouplabelIds();
        userGroupLabelRelationService.relateGroup(fromUid, toUid, relatedGrouplabelIds);

        //隐私设置
        userPrivacySetupRecordService.setupPrivacy(fromUid, toUid, relateUserGroupLabelDTO.getIsInvisible(),
            relateUserGroupLabelDTO.getIsBlock());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delUserGroupLabels(Long uid, List<Long> delLabelIds) {
        //先查询
        LabelInfoQueryBO queryParam =
            LabelInfoQueryBO.builder().labelType(LabelTypeEnum.GROUP.getCode()).createUid(uid).ids(delLabelIds).build();
        List<HeroLabelInfo> labelInfos = labelInfoService.listByParam(queryParam);
        if (CollectionUtils.isEmpty(labelInfos)) {
            log.info("用户分组标签查询为空，不删除");
            return;
        }

        List<Long> labelIds = labelInfos.stream().map(HeroLabelInfo::getId).collect(Collectors.toList());

        //删除标签
        labelInfoService.delByIds(delLabelIds, LabelTypeEnum.GROUP.getCode(), uid, false);
        //删除关联关系
        userGroupLabelRelationService.delByLabelIds(labelIds);
    }

    private List<UserGroupLabelVO> queryUserGroup(Long fromUid, Long toUid) {
        //查询fromUid所有的分组标签
        List<HeroLabelInfo> groupLabels = labelInfoService.listByParam(LabelInfoQueryBO.builder()
            .labelType(LabelTypeEnum.GROUP.getCode()).createUid(fromUid).build());
        if (CollectionUtils.isEmpty(groupLabels)) {
            log.info("用户没有分组标签 uid={}", fromUid);
            return new ArrayList<>();
        }
        List<UserGroupLabelVO> voList =
            groupLabels.stream().map(this::convertUserGroupLabelVO).collect(Collectors.toList());

        //fromUid给toUid打的标签
        List<HeroUserGroupLabelRelation> userGroupLabelRelations = userGroupLabelRelationService.listByUid(fromUid, toUid);

        //对比 赋值是否已打分组标签
        if (CollectionUtils.isNotEmpty(userGroupLabelRelations)) {
            List<Long> relatedLabelIds = userGroupLabelRelations.stream().map(HeroUserGroupLabelRelation::getLabelId)
                .collect(Collectors.toList());
            voList.forEach(vo -> {
                if (relatedLabelIds.contains(vo.getLabelId())) {
                    vo.setIsRelated(true);
                }
            });
        }
        return voList;
    }

    /**
     * 批量获取用户的分组标签
     * @param fromUid
     * @param toUids
     * @return
     */
    private Map<Long,List<UserGroupLabelVO>> queryUserGroup(Long fromUid, List<Long> toUids) {
        //查询fromUid所有的分组标签
        List<HeroLabelInfo> groupLabels = labelInfoService.listByParam(LabelInfoQueryBO.builder()
            .labelType(LabelTypeEnum.GROUP.getCode()).createUid(fromUid).build());
        if (CollectionUtils.isEmpty(groupLabels)) {
            log.info("用户没有分组标签 uid={}", fromUid);
            return Maps.newHashMap();
        }
        //k:labelId v:labelName
        Map<Long, String> labelIdNameMap =
            groupLabels.stream().collect(Collectors.toMap(HeroLabelInfo::getId, HeroLabelInfo::getLabelName));

        //fromUid给toUid打的标签; 批量的
        List<HeroUserGroupLabelRelation> userGroupLabelRelations = userGroupLabelRelationService.listByUids(fromUid, toUids);
        if(ObjectUtil.isEmpty(userGroupLabelRelations)){
            return Maps.newHashMap();
        }
        //uid分组
        Map<Long, List<HeroUserGroupLabelRelation>> groupedByUid = userGroupLabelRelations.stream()
            .collect(Collectors.groupingBy(HeroUserGroupLabelRelation::getToUid));

        //返回结果
        Map<Long,List<UserGroupLabelVO>> resultMap=Maps.newHashMap();
        groupedByUid.forEach((toUid, releations) -> {
            List<Long> relatedLabelIds = releations.stream().map(HeroUserGroupLabelRelation::getLabelId).collect(Collectors.toList());
            List<UserGroupLabelVO> userGroupLabels = relatedLabelIds.stream().map(relatedLabelId -> {
                UserGroupLabelVO labelVO = new UserGroupLabelVO();
                labelVO.setLabelId(relatedLabelId);
                labelVO.setLabelName(labelIdNameMap.get(relatedLabelId));
                return labelVO;
            }).collect(Collectors.toList());
            resultMap.put(toUid, userGroupLabels);
        });

        return  resultMap;
    }

    @Override
    public List<String> getGroupLabels(Long fromUid, Long toUid) {
        //fromUid给toUid打的标签
        List<UserGroupLabelVO> userGroupLabelVOS = queryUserGroup(fromUid, toUid);
        if(ObjectUtil.isEmpty(userGroupLabelVOS)){
            return Lists.newArrayList();
        }
        return userGroupLabelVOS.stream().map(x->x.getLabelName()).collect(Collectors.toList());
    }

    /**
     * 批量获取用户的分组标签
     * @param fromUid
     * @param toUids
     * @return
     */
    @Override
    public Map<Long,List<String>> getGroupLabels(Long fromUid, List<Long> toUids) {
        //fromUid给toUid打的标签
        Map<Long,List<UserGroupLabelVO>> userGroupLabelVOS = queryUserGroup(fromUid, toUids);
        if(ObjectUtil.isEmpty(userGroupLabelVOS)){
            return Maps.newHashMap();
        }
        return userGroupLabelVOS.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
                entry -> entry.getValue().stream().map(UserGroupLabelVO::getLabelName).collect(Collectors.toList())
        ));
    }

    private UserGroupLabelVO convertUserGroupLabelVO(HeroLabelInfo labelInfo) {
        if (labelInfo == null) {
            return null;
        }
        UserGroupLabelVO userGroupLabelVO = new UserGroupLabelVO();
        userGroupLabelVO.setLabelId(labelInfo.getId());
        userGroupLabelVO.setLabelName(labelInfo.getLabelName());
        userGroupLabelVO.setIsRelated(false);
        return userGroupLabelVO;
    }

    private HeroLabelInfo buildGroupLabel(String groupName, Long uid) {
        HeroLabelInfo heroLabelInfo = new HeroLabelInfo();
        heroLabelInfo.setLabelType(LabelTypeEnum.GROUP.getCode());
        heroLabelInfo.setLabelName(groupName);
        heroLabelInfo.setCreaterRole(CreaterRoleEnum.CUSTOMER.getCode());
        heroLabelInfo.setState(StateEnum.EFFECTIVE.getCode());
        heroLabelInfo.setCreateBy(uid);
        heroLabelInfo.setUpdateBy(uid);
        return heroLabelInfo;
    }
}
